package middleware

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"sola/db"
	"sola/session"
	"sola/utils"
)

func AuthMiddleware(c *gin.Context) {
	ProcessRequest(c)
	isLogin := IsLogin(c)
	if !isLogin {
		utils.ResponseError(c, utils.ErrCodeNotLogin)
		//中断当前请求
		c.Abort()
		return
	}
	c.Next()
}

func ProcessRequest(ctx *gin.Context) {

	var userSession session.Session

	defer func() {
		if userSession == nil {
			userSession, _ = session.CreateSession()
		}

		ctx.Set(SolaSessionName, userSession)
	}()

	//从cookie中获取session_id
	cookie, err := ctx.Request.Cookie(CookieSessionId)
	if err != nil {
		//不存在的话，设置user_id=0, login_status为0。表示未登录状态
		ctx.Set(SolaUserId, "")
		ctx.Set(SolaUserLoginStatus, int64(0))
		return
	}

	sessionId := cookie.Value
	if len(sessionId) == 0 {
		ctx.Set(SolaUserId, "")
		ctx.Set(SolaUserLoginStatus, int64(0))
		return
	}

	//根据sessionId，获取用户的session。
	userSession, err = session.Get(sessionId)
	if err != nil {
		ctx.Set(SolaUserId, "")
		ctx.Set(SolaUserLoginStatus, int64(0))
		return
	}

	tmpUserId, err := userSession.Get(SolaUserId)
	if err != nil {
		ctx.Set(SolaUserId, "")
		ctx.Set(SolaUserLoginStatus, int64(0))
		return
	}

	if tmpUserId == "" {
		ctx.Set(SolaUserId, "")
		ctx.Set(SolaUserLoginStatus, int64(0))
		return
	}

	ctx.Set(SolaUserId, tmpUserId)
	ctx.Set(SolaUserLoginStatus, int64(1))
	return
}

func GetUserId(ctx *gin.Context) (userId string, err error) {

	tempUserId, exists := ctx.Get(SolaUserId)
	if !exists || tempUserId.(string) == "" {
		err = errors.New("user id not exists")
		return
	}
	userId = tempUserId.(string)
	return
}

func IsLogin(ctx *gin.Context) (login bool) {

	tempLoginStatus, exists := ctx.Get(SolaUserLoginStatus)
	if !exists {
		return
	}

	loginStatus, ok := tempLoginStatus.(int64)
	if !ok {
		return
	}

	if loginStatus == 0 {
		return
	}

	login = true
	return
}

func SetUserId(userId string, ctx *gin.Context) {

	var userSession session.Session
	tempSession, exists := ctx.Get(SolaSessionName)
	if !exists {
		return
	}

	userSession, ok := tempSession.(session.Session)
	if !ok {
		return
	}

	if userSession == nil {
		return
	}

	userSession.Set(SolaUserId, userId)
}

func ProcessResponse(ctx *gin.Context) {

	var userSession session.Session
	tempSession, exists := ctx.Get(SolaSessionName)
	if !exists {
		return
	}

	userSession, ok := tempSession.(session.Session)
	if !ok {
		return
	}

	if userSession == nil {
		return
	}

	fmt.Printf("get session succ\n")
	if userSession.IsModify() == false {
		return
	}

	err := userSession.Save()
	if err != nil {
		return
	}
	fmt.Printf("save session succ\n")

	sessionId := userSession.Id()
	cookie := &http.Cookie{
		Name:     CookieSessionId,
		Value:    sessionId,
		MaxAge:   CookieMaxAge,
		HttpOnly: true,
		Path:     "/",
	}

	http.SetCookie(ctx.Writer, cookie)
	fmt.Printf("set cookie  succ\n")
	return
}

func GetUser(ctx *gin.Context) (user *db.User, err error) {
	var userUriInfo db.User
	if err := ctx.ShouldBindUri(&userUriInfo); err != nil {
		return user, err
	}
	user_id, err := GetUserId(ctx)
	if err != nil {
		return user, err
	}
	if userUriInfo.UserId != "" && userUriInfo.UserId != user_id {
		err = fmt.Errorf("user id is not matched")
		return user, err
	}
	user, err = db.FindUserByUserId(user_id)
	return
}
